package com.seo.textgen.pos;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Deque;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang.StringUtils;

import com.alex.utils.common.Random;
import com.seo.textgen.caseanalyser.CaseAnalyser;
import com.seo.textgen.pos.tagger.TaggedSentence;
import com.seo.textgen.pos.tagger.Token;

public class PosTaggerTextGenerator {

	private final Set<String> dontReplacePOS = new HashSet<String>(Arrays.asList("C", "SENT"));

	private CaseAnalyser caseAnalyser = new CaseAnalyser();
	
	private Lexicon lexicon;
	
	private List<TaggedSentence> sentences;
	
	private PosAwareKeywordInjector keywordInjector;

	public void train(List<TaggedSentence> sentences) throws IOException {
		this.sentences = sentences;
		trainCaseAnalyser(sentences);
		correctTokensCases(sentences);
		createLexicon(sentences);
	}

	private void correctTokensCases(List<TaggedSentence> sentences) {
		for (TaggedSentence sentence : sentences) {
			for (Token token : sentence.getTokens()) {
				token.setTokenInProperCase(caseAnalyser.getTokenInProperCase(token));
			}
		}
	}

	private void trainCaseAnalyser(List<TaggedSentence> sentences) {
		for (TaggedSentence sentence : sentences) {
			boolean startOfSentence = true;
			for (Token token : sentence.getTokens()) {
				caseAnalyser.train(token, startOfSentence);
				startOfSentence = false;
			}
		}
	}

	public String generateText(int wordCount) throws IOException {
//		wordCount = 1;
		StringBuilder text = new StringBuilder(wordCount * 10);
		
		Deque<GeneratedSentence> sentences = new LinkedList<GeneratedSentence>();
		int currentWordCount = 0;
		do {
			GeneratedSentence sentence = generateSentence();
			sentences.add(sentence);
			currentWordCount += sentence.getPlaceHolders().size();
		} while (currentWordCount < wordCount);
		
		if (keywordInjector != null) {
			keywordInjector.injectKeywords(sentences, currentWordCount);
		}
		
		for (GeneratedSentence sentence : sentences) {
			if (text.length() != 0) {
				text.append("\n");
			}
			boolean firstPart = true;
			for (Object part : sentence.getParts()) {
				if (part instanceof PlaceHolder) {
					PlaceHolder placeHolder = (PlaceHolder) part;
					if (firstPart) {
						text.append(StringUtils.capitalize(placeHolder.getValue()));
					} else {
						text.append(placeHolder.getValue());
					}
					firstPart = false;
				} else {
					text.append(part);
				}
			}
			
//			System.out.println(sentence);
//			System.out.println(sentence.getSourceSentence());
//			System.out.println("\n");
		}
		return text.toString();
	}
	
	private GeneratedSentence generateSentence() {
		int n = Random.getInt(sentences.size());
		
//		n = 739144;
		
		TaggedSentence sentence = sentences.get(n);
		
		List<Object> parts = new ArrayList<Object>(sentence.getParts().size());
		List<PlaceHolder> placeHolders = new ArrayList<PlaceHolder>(sentence.getParts().size());
		
		GeneratedSentence generatedSentence = new GeneratedSentence(sentence, parts, placeHolders);
		for (Object part : sentence.getParts()) {
			if (part instanceof Token) {
				Token token = (Token) part;
				if (!isDontReplaceToken(token)) {
					token = lexicon.getRandomSubstitution(token);
				}
				PlaceHolder placeHolder = new PlaceHolder(generatedSentence, token.getTokenInProperCase(), token);
				parts.add(placeHolder);
				placeHolders.add(placeHolder);
			} else {
				parts.add(part);
			}
		}
		
		parts.add(" " + n);
		
		return generatedSentence;
	}

	private boolean isDontReplaceToken(Token token) {
		return dontReplacePOS.contains(token.getTag());
	}

	private void createLexicon(List<TaggedSentence> sentences) {
		lexicon = new Lexicon();
		lexicon.create(sentences);
	}
	
	public void setKeywordInjector(PosAwareKeywordInjector keywordInjector) {
		this.keywordInjector = keywordInjector;
	}
}
